package net.qiqbframework.spring.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author fz51
 */
@Order(0)
public class QiqbComponentScannerConfigurer implements BeanDefinitionRegistryPostProcessor, SmartInitializingSingleton {

    private String basePackage;

    private static final Map<BeanDefinitionRegistry, ManagedConfigurerModuleRegister> contextMap = new ConcurrentHashMap<>();


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        // 扫描 module service
        if (contextMap.putIfAbsent(registry, new ManagedConfigurerModuleRegister()) == null) {
            final ManagedConfigurerModuleRegister springExecutionContext = contextMap.get(registry);
            ConfigurableListableBeanFactory beanFactory = findBeanFactory(registry);
            springExecutionContext.postProcessBeanFactory(beanFactory);

            beanFactory.registerSingleton(ManagedConfigurerModuleRegister.class.getName(), springExecutionContext);
        }
        // 将module api 注册到spring 容器里
        final ManagedConfigurerModuleRegister context = contextMap.get(registry);
        ClassPathComponentScanner scanner = new ClassPathComponentScanner(registry);
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
        context.marge(scanner.getManagedAnnotation());
    }

    private static ConfigurableListableBeanFactory findBeanFactory(BeanDefinitionRegistry registry) {
        ConfigurableListableBeanFactory beanFactory;
        if (registry instanceof ConfigurableListableBeanFactory) {
            beanFactory = (ConfigurableListableBeanFactory) registry;
        } else if (registry instanceof GenericApplicationContext genericApplicationContext) {
            beanFactory = genericApplicationContext.getBeanFactory();
        } else {
            throw new IllegalStateException("Can not find Spring BeanFactory from registry: " + registry.getClass().getName());
        }
        return beanFactory;
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }


    public void setBasePackage(String basePackage) {
        this.basePackage = basePackage;
    }

    @Override
    public void afterSingletonsInstantiated() {

    }
}
